/* SQUIB - Scala's Quirky User Interface Builder 
    Copyright (C) 2008 Tim Dalton

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
*/

package tfd.scala.squib.demo.scenario;

import java.awt.{Color, Point, Font, Dimension, Rectangle, BasicStroke}
import javax.swing.{JFrame}

import com.sun.scenario.scenegraph._
import com.sun.scenario.animation._

import tfd.scala.squib._
import tfd.scala.squib.event._
import tfd.scala.squib.scenario.scenegraph._

object RotatingCalculator extends Application {
    import java.awt.Color
    import java.awt.event.ActionEvent
    import javax.swing.{JFrame,JLabel,SwingConstants}

    // The attributes_default of a component type specify attributes that will automatically be 
    // set for any instance of that component afterward.
    //
    // The attributes_by_pattern of a component type maps regular expression to attributes 
    // that will automatically set for instances whose id mathes the regular expression 
    // that are created afterward. It's kind of a "pseudo CSS".
    // 
    // Ensure all frames exit on close
    frame.attributesDefault = attributes('defaultcloseoperation->JFrame.EXIT_ON_CLOSE)
    
    // By default make button text blue ...
    button.attributesDefault = attributes('foreground->Color.blue)
    
    // ...unless it's id is digit then red
    button.attributesByPattern += ("\\d" -> attributes('foreground->Color.red))

    // create a panel for the buttons assign to val
    // This is to show that the entire GUI doesn't have to be one
    // gigantic nesting.

    val calcField = textfield(
        'text->"0",
        'horizontalalignment->SwingConstants.RIGHT,
        'editable->false,
        'background->Color.white
    )
    
    var stored = 0.0
    var operation = ' '
    var newInput = true
    
    def doNumber(num:Int)(ae: ActionEvent) = { 
        val prepend = if (newInput) "" else calcField.getText
        calcField.setText(prepend + num)
        newInput = false
    }
    
    def doOperation(oper:Char)(ae: ActionEvent) = {
        operation = oper
        stored = calcField.getText().toDouble
        newInput = true
    }
    
    val gridPanel = panel(
        'layout -> gridlayout('rows->5, 'columns->4, 'vgap->4, 'hgap->2),
        contents(
                button(
                        'text->"C",
                        'foreground->Color.black,
                        actionPerformed {
                                calcField.setText("0")
                                newInput = true
                        }
                ),
                button(
                        'text->"CE",
                        'foreground->Color.black,
                        actionPerformed {
                                calcField.setText("0")
                                stored = 0.0
                                newInput = true
                        }),
                new JLabel(""),
                button('text->"/",     actionPerformed(doOperation('/')_)),
                button("7",'text->"7", actionPerformed(doNumber(7)_)),    
                button("8",'text->"8", actionPerformed(doNumber(8)_)),
                button("9",'text->"9", actionPerformed(doNumber(9)_)),
                button('text->"*",     actionPerformed(doOperation('/')_)),
                button("4",'text->"4", actionPerformed(doNumber(4)_)),
                button("5",'text->"5", actionPerformed(doNumber(5)_)),
                button("6",'text->"6", actionPerformed(doNumber(6)_)),
                button('text->"-",     actionPerformed(doOperation('-')_)),
                button("1",'text->"1", actionPerformed(doNumber(1)_)),
                button("2",'text->"2", actionPerformed(doNumber(2)_)),
                button("3",'text->"3", actionPerformed(doNumber(3)_)),
                button('text->"+",     actionPerformed(doOperation('+')_)),
                button("0",'text->"0", actionPerformed(doNumber(0)_)),
                button('text->"+/-", actionPerformed {  
                                   calcField.setText("" + (-calcField.getText().toDouble))
                }),
                button('text->".",  actionPerformed {
                                   if (newInput) {
                                        calcField.setText("0.")
                                        newInput = false;
                                   } else {
                                        val text = calcField.getText()
                                        if (!text.contains('.')) {
                                            calcField.setText(text + ".")
                                        }
                                   }
                }),
                button('text->"=",  actionPerformed {
                                   val current = calcField.getText().toDouble
                                   calcField.setText("" + (operation match {
                                       case '+' =>  (stored + current)
                                       case '*' =>  (stored * current)
                                       case '-' =>  (stored - current)
                                       case '/' =>  (stored / current)
                                       case _ => current
                                   }))
                                   newInput = true
                })            
        )                        
    )

    var calculatorPanel = panel(
        'layout -> borderlayout(),
        contents(
            panel("calc_panel",
                'layout-> borderlayout(),
                contents(
                    calcField -> "North", 
                    gridPanel -> "Center" 
                )
            ) -> "Center"
        )
    )
    
     text.attributesDefault = attributes(
             'font -> new Font("Courier", Font.BOLD, 24),
             'mode -> SGAbstractShape.Mode.FILL,
             'fillPaint -> Color.BLUE
     )
    
     val frm = frame(
                'title->"SQUIB Scenegraph Demo",
                'visible -> true,
                'defaultCloseOperation -> JFrame.EXIT_ON_CLOSE,
                'size -> new Dimension(300,300),
            	'layout ->  borderlayout(),
                 contents(
                         scenepanel("scene",
                              'scene -> group("root",
                                      		  translate(140,140,
                                      	      rotate("calculator", 0.0,
                                      		  translate(-85,-90,
                                      		       component(
                                                      'component -> calculatorPanel
                                      		       )
											  )))
                               ),
                              'background -> Color.GREEN
                         ) -> "Center"
                    )
    )
    
    Clip.create(
            10000, // duration
            600.0f,
            rotate.id("calculator"), // animating obj
            "rotation", // animating prop
            Array(-3.14159f, 3.14159f).map(_.asInstanceOf[Object]):_* // "to" value
    ).start();
}
